/*--------------------------------------------------------------------------------*/
#include "application.h"
/*--------------------------------------------------------------------------------*/
#include <SDL/SDL.h>
#include "util.h"
#include "debug.h"
#include "graphic_2d_renderer.h"
#include "graphic_extension_manager.h"
#include "input_file_manager.h"
#include "input_system.h"
#include "graphic_texture_manager.h"
#include "graphic_animation_manager.h"
#include "graphic_particle_manager.h"
#include "graphic_font_manager.h"
/*--------------------------------------------------------------------------------*/
IMPLEMENT_SINGLETON( APPLICATION );
/*--------------------------------------------------------------------------------*/
APPLICATION::APPLICATION() :
	OBJECT(),
    ItIsRunning( false ),
    Width( 800 ),
    Height( 600 ),
    Name( "Unnamed ggpvision application" ),
    RenderSurface( NULL )
{

}
/*--------------------------------------------------------------------------------*/
APPLICATION::~APPLICATION()
{
}
/*--------------------------------------------------------------------------------*/
VOID APPLICATION::Initialize( const BOOL fullscreen, const BOOL create_all_instances )
{
    DEBUG_LogLine( "APPLICATION::Initialize()" );

    SDL_Init( SDL_INIT_VIDEO );

    SDL_WM_SetCaption( Name.GetArray(), "Title" );

    if( fullscreen )
    {
    	RenderSurface = SDL_SetVideoMode( Width, Height, 32, SDL_OPENGL | SDL_FULLSCREEN );
    }
    else
    {
    	RenderSurface = SDL_SetVideoMode( Width, Height, 32, SDL_OPENGL );
    }

    DEBUG_CheckOpenGL();

	glClearDepth( 1.0f );
	glHint( GL_LINE_SMOOTH_HINT,GL_FASTEST );
	glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST );
	glHint( GL_LINE_SMOOTH_HINT,GL_NICEST );
	glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
	glShadeModel( GL_SMOOTH );

	glAlphaFunc( GL_GREATER, 0.5f );
	glEnable( GL_ALPHA_TEST );
	//glEnable( GL_BLEND );

	DEBUG_CheckOpenGL();

	if( create_all_instances )
	{
		GRAPHIC_2D_RENDERER::CreateInstance();
		GRAPHIC_EXTENSION_MANAGER::CreateInstance();
		INPUT_FILE_MANAGER::CreateInstance();
		INPUT_SYSTEM::CreateInstance();
		GRAPHIC_TEXTURE_MANAGER::CreateInstance();
		GRAPHIC_ANIMATION_MANAGER::CreateInstance();
		GRAPHIC_PARTICLE_MANAGER::CreateInstance();
		GRAPHIC_FONT_MANAGER::CreateInstance();
	}
}
/*--------------------------------------------------------------------------------*/
VOID APPLICATION::Start()
{
    TIMER
		current_time(0),
		old_time(0);
    SDL_Event
		event;

    DEBUG_LogLine( "APPLICATION::Start()" );
    ItIsRunning = true;

    EnableMode2d();

    old_time = TIMER::GetCurrentTime();

    while( ItIsRunning )
    {
    	SDL_PollEvent( &event );
		ItIsRunning = !( event.type == SDL_QUIT );
		
        current_time = TIMER::GetCurrentTime();

        glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
        glLoadIdentity();

        UpdateCallBack( current_time - old_time );
        RenderCallBack();

        SDL_GL_SwapBuffers();
        SDL_UpdateRect( RenderSurface, 0, 0, 0, 0 );

        
        old_time = current_time;
    }

    End();
}
/*--------------------------------------------------------------------------------*/
VOID APPLICATION::StartUsingStateChart( const COMPONENT_STATE_CHART * state_chart )
{
    TIMER
		current_time(0),
		old_time(0);
    SDL_Event
		event;

    DEBUG_LogLine( "APPLICATION::Start()" );
    ItIsRunning = true;

    EnableMode2d();

    old_time = TIMER::GetCurrentTime();

    while( ItIsRunning )
    {
    	SDL_PollEvent( &event );
		ItIsRunning = !( event.type == SDL_QUIT );

        current_time = TIMER::GetCurrentTime();

        glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
        glLoadIdentity();

        ( ( COMPONENT_STATE_CHART * )state_chart )->Update( current_time - old_time );

        SDL_GL_SwapBuffers();
        SDL_UpdateRect( RenderSurface, 0, 0, 0, 0 );


        old_time = current_time;
    }

    End();
}
/*--------------------------------------------------------------------------------*/
VOID APPLICATION::Quit()
{
	ItIsRunning = false;
}
/*--------------------------------------------------------------------------------*/
VOID APPLICATION::SetName( const TEXT & name )
{
    Name = name;
}
/*--------------------------------------------------------------------------------*/
VOID APPLICATION::SetExtent( const INT & width, const INT & height )
{
    Width = width;
    Height = height;
}
/*--------------------------------------------------------------------------------*/
VOID APPLICATION::SetRenderCallBack( VOID ( *call_back )() )
{
    RenderCallBack = call_back;
}
/*--------------------------------------------------------------------------------*/
VOID APPLICATION::SetUpdateCallBack( VOID ( *call_back )( const TIMER & time_step  ) )
{
    UpdateCallBack = call_back;
}
/*--------------------------------------------------------------------------------*/
VOID APPLICATION::SetClearColor( const COLOR & color )
{
	glClearColor( color.Red, color.Green, color.Blue, color.Alpha );
}
/*--------------------------------------------------------------------------------*/
VOID APPLICATION::End()
{
	DEBUG_LogLine( "APPLICATION::End()" );
	SDL_Quit();
    GRAPHIC_TEXTURE_MANAGER::RemoveInstance();
    GRAPHIC_ANIMATION_MANAGER::RemoveInstance();
    GRAPHIC_2D_RENDERER::RemoveInstance();
    GRAPHIC_EXTENSION_MANAGER::RemoveInstance();
    INPUT_FILE_MANAGER::RemoveInstance();
    INPUT_SYSTEM::RemoveInstance();
}
/*--------------------------------------------------------------------------------*/
VOID APPLICATION::EnableMode2d()
{
    glMatrixMode( GL_PROJECTION );
 	glLoadIdentity ();
 	gluOrtho2D ( - (GLdouble)Width/2.0f, (GLdouble)Width/2.0f, - (GLdouble)Height/2.0f, (GLdouble)Height/2.0f );
    glViewport( 0, 0, Width, Height );
    glMatrixMode( GL_MODELVIEW );

    /*
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	float aspect_ratio = ((float)Height) / Width;
	glFrustum(.5, -.5, -.5 * aspect_ratio, .5 * aspect_ratio, 1, 50);
	glMatrixMode(GL_MODELVIEW);*/

}
/*--------------------------------------------------------------------------------*/
